//===============================================================================
// Microsoft patterns & practices
// Web Client Software Factory
//-------------------------------------------------------------------------------
// Copyright (C) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//-------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================
using System;
using System.Runtime.Remoting.Messaging;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;

namespace WCSFContrib.PageFlow.WorkflowFoundation.Activities
{
	public partial class PageFlow : IActivityEventListener<QueueEventArgs>
	{
		private static IComparable GetDataQueueName = new EventQueueName(typeof (IDataExchangeService), "GetData");
		private static IComparable SetDataQueueName = new EventQueueName(typeof (IDataExchangeService), "SetData");
		private static IComparable DisposeDataQueueName = new EventQueueName(typeof (IDataExchangeService), "DisposeData");
		private static IComparable GetKeysQueueName = new EventQueueName(typeof (IDataExchangeService), "GetKeys");

		/// <summary>
		/// Implementation of the OnEvent() method of the IActivityEventListener interface
		/// which enables the <see cref="Activity">Activity</see> to process events.
		/// </summary>
		/// <param name="sender">The object that raised the event.</param>
		/// <param name="e">The previously typed event arguments.</param>
		public void OnEvent(object sender, QueueEventArgs e)
		{
			IDataExchangeService service = GetDataExchangeService(sender);
			if (e.QueueName.CompareTo(GetDataQueueName) == 0)
				OnGetData(GetEventArgs<DataKeyEventArgs>(sender, e), service);
			if (e.QueueName.CompareTo(SetDataQueueName) == 0)
				OnSetData(GetEventArgs<SetDataEventArgs>(sender, e));
			if (e.QueueName.CompareTo(DisposeDataQueueName) == 0)
				OnDisposeData(GetEventArgs<DataKeyEventArgs>(sender, e));
			if (e.QueueName.CompareTo(GetKeysQueueName) == 0)
				OnGetKeys(GetEventArgs<DataKeyEventArgs>(sender, e), service);
		}

		private void OnGetKeys(DataKeyEventArgs dataKeyEventArgs, IDataExchangeService service)
		{
			service.FireGetKeysReturned(dataKeyEventArgs.InstanceId, UserDataStore.Keys);
		}

		private void OnDisposeData(DataKeyEventArgs dataKeyEventArgs)
		{
			if (UserDataStore.ContainsKey(dataKeyEventArgs.Key))
			{
				UserDataStore.Remove(dataKeyEventArgs.Key);
			}
		}

		private void OnSetData(SetDataEventArgs setDataEventArgs)
		{
			if (UserDataStore.ContainsKey(setDataEventArgs.Key))
			{
				UserDataStore.Remove(setDataEventArgs.Key);
			}
			UserDataStore.Add(setDataEventArgs.Key, setDataEventArgs.Value);
		}

		private void OnGetData(DataKeyEventArgs e, IDataExchangeService service)
		{
			object value = null;
			if (UserDataStore.ContainsKey(e.Key))
			{
				value = UserDataStore[e.Key];
			}
			service.FireDataReturned(WorkflowInstanceId, value);
		}

		private static IDataExchangeService GetDataExchangeService(object sender)
		{
			return (IDataExchangeService) ((ActivityExecutionContext) sender).GetService(typeof (IDataExchangeService));
		}

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
        private static T GetEventArgs<T>(object sender, QueueEventArgs e)
		{
			ActivityExecutionContext executionContext = (ActivityExecutionContext) sender;
			WorkflowQueuingService queuingService =
				(WorkflowQueuingService) executionContext.GetService(typeof (WorkflowQueuingService));
			WorkflowQueue pageFlowQueue = queuingService.GetWorkflowQueue(e.QueueName);
			IMethodMessage message = (IMethodMessage) pageFlowQueue.Dequeue();
			return (T) message.Args[1];
		}

		/// <summary>
		/// Called by the workflow runtime to execute an activity. 
		/// </summary>
		/// <param name="executionContext">The <see cref="ActivityExecutionContext">ActivityExecutionContext</see> 
		/// to associate with this Activity and execution.</param>
		/// <returns>Returns the status that represents the current status of an Activity instance within a workflow instance. </returns>
		protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
		{
			WorkflowQueuingService queuingService =
				(WorkflowQueuingService) executionContext.GetService(typeof (WorkflowQueuingService));
			queuingService.CreateWorkflowQueue(GetDataQueueName, true).RegisterForQueueItemAvailable(this, QualifiedName);
			queuingService.CreateWorkflowQueue(SetDataQueueName, true).RegisterForQueueItemAvailable(this, QualifiedName);
			queuingService.CreateWorkflowQueue(DisposeDataQueueName, true).RegisterForQueueItemAvailable(this, QualifiedName);
			queuingService.CreateWorkflowQueue(GetKeysQueueName, true).RegisterForQueueItemAvailable(this, QualifiedName);

			return base.Execute(executionContext);
		}
	}
}
